﻿using cszmcaux;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Zmotionlib
{
    class ZmotionHelper
    {
        //设置轴类型
        /*
         Atype类型 描述
        0 虚拟轴。
        1 脉冲方向方式的步进或伺服 。
        2 模拟信号控制方式的伺服 。
        3 正交编码器 。
        4 步进+编码器 。
        6 脉冲方向方式的编码器，可用于手轮输入。
        7 脉冲方向方式步进或伺服+EZ信号输入。
        8 ZCAN扩展脉冲方向方式步进或伺服 。
        9 ZCAN扩展正交编码器。
        10 ZCAN扩展脉冲方向方式的编码器。
         */

        private string _ipAderss = null;
        private IntPtr _pHandle;

        public bool InitedOK { get; set; }       //初始化完成标志
        public int unit0 { get; set; } = 400;    //设置脉冲当量-电机转一圈所需要的脉冲数
        public int unit1 { get; set; } = 400;
        public int unit2 { get; set; } = 400;
        public int unit3 { get; set; } = 400;
        public int Timeout { get; set; } = 10000; //超时时间

        ZmotionHelper(string ipAderss="127.0.0.1" )
        {
            this._ipAderss=ipAderss;
        }

        /// <summary>
        /// 获取本机所有IP地址
        /// </summary>
        /// <returns>List<string></returns>
        public static List<string> GetIPList()
        {
            List<string> ipAddresses = new List<string>();
            NetworkInterface[] network = NetworkInterface.GetAllNetworkInterfaces();
            try
            {
                foreach (NetworkInterface networkInterface in network)
                {
                    if (networkInterface.OperationalStatus != OperationalStatus.Up &&
                       networkInterface.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                    {
                        /* 获取网络接口的 IP 配置信息（包括 IP 地址、子网掩码、网关等）*/
                        IPInterfaceProperties ipProperty = networkInterface.GetIPProperties();
                        /* 获取该接口的所有 单播 IP 地址（即实际分配给接口的 IP 地址，如 192.168.1.100）*/
                        UnicastIPAddressInformationCollection unicastAddresses = ipProperty.UnicastAddresses;
                        foreach (var item in unicastAddresses)
                        {
                            /* 只获取IPV4的地址*/
                            if (item.Address.AddressFamily == AddressFamily.InterNetwork)
                            {
                                ipAddresses.Add(item.Address.ToString());
                            }
                        }
                    }
                }
                //Dns对应的IP
                if (ipAddresses.Count > 0)
                {
                    IPAddress[] IP = Dns.GetHostAddresses(Dns.GetHostName());
                    foreach (var ipAddress in IP)
                    {
                        if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
                        {
                            ipAddresses.Add(ipAddress.ToString());
                        }

                    }
                }
                if(ipAddresses.Count > 0)
                {
                    return ipAddresses;
                }
                else
                {
                    return new List<string>();
                }
            }
            catch (Exception)
            {
                throw;
            }
           
        }

        /// <summary>
        /// 连接板卡
        /// </summary>
        /// <returns>OPerationResult</returns>
        public OPerationResult InitCard()
        {
            int error = zmcaux.ZAux_OpenEth(_ipAderss, out _pHandle);
            if( error == 0 && _pHandle != IntPtr.Zero)
            {
                InitedOK = true;
                return OPerationResult.Ok();
            }
            else
            {
                InitedOK = false;
                return OPerationResult.Fail();
            }

        }

        /// <summary>
        /// 关闭板卡
        /// </summary>
        /// <returns>OPerationResult</returns>
        public OPerationResult CloseCard()
        {
            if (zmcaux.ZAux_Close(_pHandle) == 0)
            {
                InitedOK = false;
                _pHandle = IntPtr.Zero;
                return OPerationResult.Ok();
            }
            return OPerationResult.Fail();
        }

        /// <summary>
        /// 轴连续运动，配合停止使用
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <param name="velocity">速度</param>
        /// <param name="direction">方向 false：-1，True：1</param>
        /// <param name="velocityMin">最小速度</param>
        /// <param name="acc">加速度</param>
        /// <param name="dec">减速度</param>
        /// <param name="sramp">s曲线（时间）</param>
        /// <param name="axisType">轴类型</param>
        /// <returns>OPerationResult</returns>
        public OPerationResult Vmove( short axis,float velocity,bool direction,float velocityMin,float acc,float dec,float sramp,int axisType)
        {
            //判断轴是否连接或在运行中
            var result = CommonInitedValidate(axis);
            if(!result.IsSucess) return result;

            int error = 0; //错误编号
            try
            {
                //设置轴类型
                error = zmcaux.ZAux_Direct_SetAtype(_pHandle, axis, axisType);
                Error_pHandle("ZAux_Direct_SetAtype", error);

                //设置脉冲当量
                switch (axis)
                {
                    case 0:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit0);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 1:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit1);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 2:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit2);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 3:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit3);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    default:
                        break;
                }

                //设置最小速度
                error = zmcaux.ZAux_Direct_SetLspeed(_pHandle,axis,velocityMin);
                Error_pHandle("ZAux_Direct_SetLspeed",error);

                //设置运行速度
                error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis, velocity);
                Error_pHandle("ZAux_Direct_SetSpeed", error);

                //设置加速度
                error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis, acc);
                Error_pHandle("ZAux_Direct_SetAccel", error);

                //设置减速度
                error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis, dec);
                Error_pHandle("ZAux_Direct_SetDecel", error);

                //设置S曲线：能够让运动更加平滑一些
                error = zmcaux.ZAux_Direct_SetSramp(_pHandle, axis, sramp);
                Error_pHandle("ZAux_Direct_SetSramp", error);

                //设置方向并运动
                error = zmcaux.ZAux_Direct_Single_Vmove(_pHandle, axis, direction ? 1 : -1);
                Error_pHandle("ZAux_Direct_Single_Vmove", error);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();

        }

        /// <summary>
        /// 相对定位
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="velocity"></param>
        /// <param name="distance"></param>
        /// <param name="velocityMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <param name="axisType"></param>
        /// <returns>OPerationResult</returns>
        public OPerationResult MoveRelative(short axis, float velocity,float distance , float velocityMin, float acc, float dec, float sramp, int axisType)
        {
            
            var result = CommonInitedValidate(axis);
            if (!result.IsSucess) return result;

            int error = 0; //错误编号
            try
            {
                //设置轴类型
                error = zmcaux.ZAux_Direct_SetAtype(_pHandle, axis, axisType);
                Error_pHandle("ZAux_Direct_SetAtype", error);

                //设置脉冲当量
                switch (axis)
                {
                    case 0:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit0);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 1:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit1);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 2:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit2);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 3:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit3);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    default:
                        break;
                }

                //设置最小速度
                error = zmcaux.ZAux_Direct_SetLspeed(_pHandle, axis, velocityMin);
                Error_pHandle("ZAux_Direct_SetLspeed", error);

                //设置运行速度
                error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis, velocity);
                Error_pHandle("ZAux_Direct_SetSpeed", error);

                //设置加速度
                error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis, acc);
                Error_pHandle("ZAux_Direct_SetAccel", error);

                //设置减速度
                error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis, dec);
                Error_pHandle("ZAux_Direct_SetDecel", error);

                //设置S曲线：能够让运动更加平滑一些
                error = zmcaux.ZAux_Direct_SetSramp(_pHandle, axis, sramp);
                Error_pHandle("ZAux_Direct_SetSramp", error);

                //运动
                error = zmcaux.ZAux_Direct_Single_Move(_pHandle, axis,distance);
                Error_pHandle("ZAux_Direct_Single_Move", error);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();

        }

        /// <summary>
        /// 绝对定位
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="velocity"></param>
        /// <param name="distance"></param>
        /// <param name="velocityMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp">）</param>
        /// <param name="axisType"></param>
        /// <returns>OPerationResult</returns>
        public OPerationResult MoveAbs(short axis, float velocity, float distance, float velocityMin, float acc, float dec, float sramp, int axisType)
        {

            var result = CommonInitedValidate(axis);
            if (!result.IsSucess) return result;

            int error = 0; //错误编号
            try
            {
                //设置轴类型
                error = zmcaux.ZAux_Direct_SetAtype(_pHandle, axis, axisType);
                Error_pHandle("ZAux_Direct_SetAtype", error);

                //设置脉冲当量
                switch (axis)
                {
                    case 0:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit0);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 1:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit1);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 2:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit2);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 3:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit3);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    default:
                        break;
                }

                //设置最小速度
                error = zmcaux.ZAux_Direct_SetLspeed(_pHandle, axis, velocityMin);
                Error_pHandle("ZAux_Direct_SetLspeed", error);

                //设置运行速度
                error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis, velocity);
                Error_pHandle("ZAux_Direct_SetSpeed", error);

                //设置加速度
                error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis, acc);
                Error_pHandle("ZAux_Direct_SetAccel", error);

                //设置减速度
                error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis, dec);
                Error_pHandle("ZAux_Direct_SetDecel", error);

                //设置S曲线：能够让运动更加平滑一些
                error = zmcaux.ZAux_Direct_SetSramp(_pHandle, axis, sramp);
                Error_pHandle("ZAux_Direct_SetSramp", error);

                //运动
                error = zmcaux.ZAux_Direct_Single_MoveAbs(_pHandle, axis, distance);
                Error_pHandle("ZAux_Direct_Single_MoveAbs", error);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();

        }

        /// <summary>
        /// 二维相对定位
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="velocity"></param>
        /// <param name="distance"></param>
        /// <param name="velocityMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <param name="axisType"></param>
        /// <returns></returns>
        public OPerationResult Move2DRelative(short[] axis, float[] velocity, float[] distance, float[] velocityMin, float[] acc, float[] dec, float[] sramp, int[] axisType)
        {
            if(axis.Length==2 && velocity.Length==2 && distance.Length ==2 && velocityMin.Length==2 &&
                acc.Length==2 && dec.Length==2 && sramp.Length==2 && axisType.Length == 2)
            {
                OPerationResult result = new OPerationResult();

                //执行相对定位
                for(int i = 0;i < axis.Length; i++)
                {
                    result = MoveRelative(axis[i], velocity[i], distance[i], velocityMin[i], acc[i], dec[i], sramp[i], axisType[i]);
                    if (!result.IsSucess)
                    {
                        return result;
                    }
                }
                //等待执行完毕
                for(int i =0; i < axis.Length; i++)
                {
                    result = WaitStop(axis[i]);
                    if(!result.IsSucess) return result;
                }
            }
            return new OPerationResult
            {
                IsSucess = false,
                ErrorMessage = "传入参数长度不正确"
            };
        }

        /// <summary>
        /// 二维绝对定位
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="velocity"></param>
        /// <param name="distance"></param>
        /// <param name="velocityMin"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="sramp"></param>
        /// <param name="axisType"></param>
        /// <returns></returns>
        public OPerationResult Move2DAbs(short[] axis, float[] velocity, float[] distance, float[] velocityMin, float[] acc, float[] dec, float[] sramp, int[] axisType)
        {
            if (axis.Length == 2 && velocity.Length == 2 && distance.Length == 2 && velocityMin.Length == 2 &&
                acc.Length == 2 && dec.Length == 2 && sramp.Length == 2 && axisType.Length == 2)
            {
                OPerationResult result = new OPerationResult();

                //执行绝对定位
                for (int i = 0; i < axis.Length; i++)
                {
                    result = MoveAbs(axis[i], velocity[i], distance[i], velocityMin[i], acc[i], dec[i], sramp[i], axisType[i]);
                    if (!result.IsSucess)
                    {
                        return result;
                    }
                }
                //等待执行完毕
                for (int i = 0; i < axis.Length; i++)
                {
                    result = WaitStop(axis[i]);
                    if (!result.IsSucess) return result;
                }
            }
            return new OPerationResult
            {
                IsSucess = false,
                ErrorMessage = "传入参数长度不正确"
            };
        }

        /// <summary>
        /// 多轴相对直线插补
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <returns></returns>
        public OPerationResult MoveLineRelation(int[] axis, float[] distance, float vel,float acc,float dec)
        {
            if(axis.Length >=2 && axis.Length == distance.Length)
            {
                OPerationResult result = new OPerationResult();
                foreach (var item in axis)//判断每个轴条件是否满足
                {
                    result= CommonInitedValidate((short)item);
                    if (!result.IsSucess) return result;
                }

                int error = 0; //错误编号
                try
                {
                    error = zmcaux.ZAux_Direct_Base(_pHandle, axis.Length, axis);
                    Error_pHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis[0], vel);
                    Error_pHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis[0], acc);
                    Error_pHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis[0], dec);
                    Error_pHandle("ZAux_Direct_SetDecel", error);

                    //执行
                    error = zmcaux.ZAux_Direct_Move(_pHandle, axis.Length, axis, distance);
                    Error_pHandle("ZAux_Direct_Move", error);

                    return OPerationResult.Ok();
                }
                catch (Exception ex)
                {
                    result.IsSucess = false;
                    result.ErrorMessage = ex.Message;
                    return result;
                }

            }
            return new OPerationResult()
            {
                IsSucess = false,
                ErrorMessage = "传递参数不正确"
            };
        }

        /// <summary>
        /// 多轴绝对直线插补
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <returns></returns>
        public OPerationResult MoveLineAbs(int[] axis, float[] distance, float vel, float acc, float dec)
        {
            if (axis.Length >= 2 && axis.Length == distance.Length)
            {
                OPerationResult result = new OPerationResult();
                foreach (var item in axis)//判断每个轴条件是否满足
                {
                    result = CommonInitedValidate((short)item);
                    if (!result.IsSucess) return result;
                }

                int error = 0; //错误编号
                try
                {
                    error = zmcaux.ZAux_Direct_Base(_pHandle, axis.Length, axis);
                    Error_pHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis[0], vel);
                    Error_pHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis[0], acc);
                    Error_pHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis[0], dec);
                    Error_pHandle("ZAux_Direct_SetDecel", error);

                    //执行
                    error = zmcaux.ZAux_Direct_MoveAbs(_pHandle, axis.Length, axis, distance);
                    Error_pHandle("ZAux_Direct_MoveAbs", error);

                    return OPerationResult.Ok();
                }
                catch (Exception ex)
                {
                    result.IsSucess = false;
                    result.ErrorMessage = ex.Message;
                    return result;
                }

            }
            return new OPerationResult()
            {
                IsSucess = false,
                ErrorMessage = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧相对插补（圆心定位）
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="circlecenter"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public OPerationResult MoveCircleRelative(int[] axis, float[] distance, float[] circlecenter,float vel,float acc,float dec,int direction)
        {
            if(axis.Length ==2 && axis.Length == distance.Length)
            {
                OPerationResult result = new OPerationResult();
                foreach (var item in axis)//判断每个轴条件是否满足
                {
                    result = CommonInitedValidate((short)item);
                    if (!result.IsSucess) return result;
                }
                int error = 0; //错误编号
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(_pHandle, axis.Length, axis);
                    Error_pHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis[0], vel);
                    Error_pHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis[0], acc);
                    Error_pHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis[0], dec);
                    Error_pHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc(_pHandle, axis.Length, axis, distance[0], distance[1], circlecenter[0], circlecenter[1], direction);
                    Error_pHandle("ZAux_Direct_MoveCirc", error);

                    return OPerationResult.Ok();
                }
                catch (Exception ex)
                {
                    result.IsSucess = false;
                    result.ErrorMessage = ex.Message;
                    return result;
                }
            }
            return new OPerationResult()
            {
                IsSucess = false,
                ErrorMessage = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧绝对插补（圆心定位）
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="circlecenter"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="dec"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public OPerationResult MoveCircleAbs(int[] axis, float[] distance, float[] circlecenter, float vel, float acc, float dec, int direction)
        {
            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OPerationResult result = new OPerationResult();
                foreach (var item in axis)//判断每个轴条件是否满足
                {
                    result = CommonInitedValidate((short)item);
                    if (!result.IsSucess) return result;
                }
                int error = 0; //错误编号
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(_pHandle, axis.Length, axis);
                    Error_pHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis[0], vel);
                    Error_pHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis[0], acc);
                    Error_pHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis[0], dec);
                    Error_pHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCircAbs(_pHandle, axis.Length, axis, distance[0], distance[1], circlecenter[0], circlecenter[1], direction);
                    Error_pHandle("ZAux_Direct_MoveCircAbs", error);

                    return OPerationResult.Ok();
                }
                catch (Exception ex)
                {
                    result.IsSucess = false;
                    result.ErrorMessage = ex.Message;
                    return result;
                }
            }
            return new OPerationResult()
            {
                IsSucess = false,
                ErrorMessage = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧相对插补（中点定位）
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="midpos"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public OPerationResult MoveCircle2Relative(int[] axis, float[] distance, float[] midpos, float vel, float acc, float dec)
        {
            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OPerationResult result = new OPerationResult();
                foreach (var item in axis)//判断每个轴条件是否满足
                {
                    result = CommonInitedValidate((short)item);
                    if (!result.IsSucess) return result;
                }
                int error = 0; //错误编号
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(_pHandle, axis.Length, axis);
                    Error_pHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis[0], vel);
                    Error_pHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis[0], acc);
                    Error_pHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis[0], dec);
                    Error_pHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc2(_pHandle, axis.Length, axis, distance[0], distance[1], midpos[0], midpos[1]);
                    Error_pHandle("ZAux_Direct_MoveCirc2", error);

                    return OPerationResult.Ok();
                }
                catch (Exception ex)
                {
                    result.IsSucess = false;
                    result.ErrorMessage = ex.Message;
                    return result;
                }
            }
            return new OPerationResult()
            {
                IsSucess = false,
                ErrorMessage = "传递参数不正确"
            };
        }

        /// <summary>
        /// XY圆弧绝对插补（中点定位）
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="distance"></param>
        /// <param name="midpos"></param>
        /// <param name="vel"></param>
        /// <param name="acc"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public OPerationResult MoveCircle2Abs(int[] axis, float[] distance, float[] midpos, float vel, float acc, float dec)
        {
            if (axis.Length == 2 && axis.Length == distance.Length)
            {
                OPerationResult result = new OPerationResult();
                foreach (var item in axis)//判断每个轴条件是否满足
                {
                    result = CommonInitedValidate((short)item);
                    if (!result.IsSucess) return result;
                }
                int error = 0; //错误编号
                try
                {
                    //选择 BASE 轴列表
                    error = zmcaux.ZAux_Direct_Base(_pHandle, axis.Length, axis);
                    Error_pHandle("ZAux_Direct_Base", error);

                    error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis[0], vel);
                    Error_pHandle("ZAux_Direct_SetSpeed", error);

                    error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis[0], acc);
                    Error_pHandle("ZAux_Direct_SetAccel", error);

                    error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis[0], dec);
                    Error_pHandle("ZAux_Direct_SetDecel", error);

                    error = zmcaux.ZAux_Direct_MoveCirc2Abs(_pHandle, axis.Length, axis, distance[0], distance[1], midpos[0], midpos[1]);
                    Error_pHandle("ZAux_Direct_MoveCirc2Abs", error);

                    return OPerationResult.Ok();
                }
                catch (Exception ex)
                {
                    result.IsSucess = false;
                    result.ErrorMessage = ex.Message;
                    return result;
                }
            }
            return new OPerationResult()
            {
                IsSucess = false,
                ErrorMessage = "传递参数不正确"
            };
        }

        /// <summary>
        /// 通用回零操作
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <param name="vel">速度</param>
        /// <param name="creep">爬行速度</param>
        /// <param name="homeio">HomeIO</param>
        /// <param name="distance">原限距离</param>
        /// <param name="velMin">最小速度</param>
        /// <param name="acc">加速度</param>
        /// <param name="dec">减速度</param>
        /// <param name="sramp">s曲线时间</param>
        /// <param name="homemode">回零模式</param>
        /// <returns>操作结果</returns>
        public OPerationResult ZeroAxis(short axis, float vel, float creep, int homeio, float distance, float velMin, float acc, float dec, float sramp, int homemode = 4)
        {
            // 判断是否满足运动条件
            var result = CommonInitedValidate(axis);

            if (!result.IsSucess) return result;

            //先往原点方向一直走，直到到达限位
            result = MoveRelative(axis, vel, -500, velMin, acc, dec, sramp,1);
            if (!result.IsSucess) return result;

            //等待停止
            result = WaitStop(axis);
            if (!result.IsSucess) return result;

            //位置
            result = ZeroPos(axis);
            if (!result.IsSucess) return result;

            //往反向走一段距离，超过原点和限位的距离
            result = MoveRelative(axis, vel, distance, velMin, acc, dec, sramp,1);
            if (!result.IsSucess) return result;

            //等待停止
            result = WaitStop(axis);
            if (!result.IsSucess) return result;

            //直接回零
            result = DirectZeroAxis(axis, vel, creep, homeio, velMin, acc, dec, homemode);
            if (!result.IsSucess) return result;

            //等待回零停止
            result = WaitHomeStop(axis);
            if (!result.IsSucess) return result;

            //返回成功
            return OPerationResult.Ok();

        }

        /// <summary>
        /// 直接回原点
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <param name="vel">速度</param>
        /// <param name="creep">爬行速度</param>
        /// <param name="homeio">原点IO点</param>
        /// <param name="velMin">最小速度</param>
        /// <param name="acc">加速度</param>
        /// <param name="dec">减速度</param>
        /// <param name="homemode">回零模式</param>
        /// <returns>操作</returns>
        public OPerationResult DirectZeroAxis(short axis, float vel, float creep, int homeio, float velMin, float acc, float dec, int homemode = 4)
        {
            // 判断是否满足运动条件
            var result = CommonInitedValidate(axis);

            if (!result.IsSucess) return result;

            //创建错误码
            int error = 0;

            try
            {
                //设置轴类型
                error = zmcaux.ZAux_Direct_SetAtype(_pHandle, axis, 1);
                Error_pHandle("ZAux_Direct_SetAtype", error);

                //设置脉冲当量
                switch (axis)
                {
                    case 0:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit0);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 1:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit1);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 2:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit2);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    case 3:
                        error = zmcaux.ZAux_Direct_SetUnits(_pHandle, axis, unit3);
                        Error_pHandle("ZAux_Direct_SetUnits", error);
                        break;
                    default:
                        break;
                }

                //设置最小速度
                error = zmcaux.ZAux_Direct_SetLspeed(_pHandle, axis, velMin);
                Error_pHandle("ZAux_Direct_SetLspeed", error);

                //设置运行速度
                error = zmcaux.ZAux_Direct_SetSpeed(_pHandle, axis, vel);
                Error_pHandle("ZAux_Direct_SetSpeed", error);

                //设置加速度
                error = zmcaux.ZAux_Direct_SetAccel(_pHandle, axis, acc);
                Error_pHandle("ZAux_Direct_SetAccel", error);

                //设置减速度
                error = zmcaux.ZAux_Direct_SetDecel(_pHandle, axis, dec);
                Error_pHandle("ZAux_Direct_SetDecel", error);

                //设置爬行速度
                error = zmcaux.ZAux_Direct_SetCreep(_pHandle, axis, creep);
                Error_pHandle("ZAux_Direct_SetCreep", error);

                //设置HomeIO
                error = zmcaux.ZAux_Direct_SetDatumIn(_pHandle, axis, homeio);
                Error_pHandle("ZAux_Direct_SetDatumIn", error);

                //执行回原点
                error = zmcaux.ZAux_Direct_Single_Datum(_pHandle, axis, homemode);
                Error_pHandle("ZAux_Direct_Single_Datum", error);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();
        }

        /// <summary>
        /// 位置清零
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public OPerationResult ZeroPos(short axis)
        {
            //判断是否满足初始化条件
            var result = CommonInitedValidate();

            if (!result.IsSucess) return result;

            //定义错误码
            int error = 0;

            try
            {
                error = zmcaux.ZAux_Direct_SetMpos(_pHandle, axis, 0.0f);
                Error_pHandle("ZAux_Direct_SetMpos", error);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();
        }

        /// <summary>
        /// 轴停止
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <param name="imodel">停止模式 0-取消当前运动 1-取消缓冲运动 2-取消当前运动和缓冲运动 3-立即中断脉冲发送</param>
        /// <returns>OPerationResult</returns>
        public OPerationResult StopeAxis(short axis,int imodel)
        {
            var result = CommonInitedValidate();
            if(!result.IsSucess) return result;

            int error = 0; //错误编号

            try
            {
                error = zmcaux.ZAux_Direct_Single_Cancel(_pHandle, axis, imodel);
                Error_pHandle("ZAux_Direct_Single_Cancel",error);
            }
            catch (Exception ex)
            {
                result.IsSucess=false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();
        }

        /// <summary>
        /// 等待轴停止
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public OPerationResult WaitStop(short axis)
        {
            var result = CommonInitedValidate();
            if(!result.IsSucess) return result;

            int error = 0;
            int runstate = 0;    //运行状态 0-运动中 -1 停止
            var sw = Stopwatch.StartNew();
            try
            {
                do
                {
                    error = zmcaux.ZAux_Direct_GetIfIdle(_pHandle, axis, ref runstate);
                    Error_pHandle("ZAux_Direct_GetIfIdle", error);
                    if (sw.ElapsedMilliseconds > Timeout)
                        throw new TimeoutException("等待轴空闲超时!");
                } while (runstate == 0);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();
        }

        /// <summary>
        /// 等待回零停止
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <returns></returns>
        public OPerationResult WaitHomeStop(short axis)
        {
            // 判断是否满足初始化条件
            var result = CommonInitedValidate();

            if (!result.IsSucess) return result;


            int error = 0;

            uint homestate = 0;

            do
            {
                error = zmcaux.ZAux_Direct_GetHomeStatus(_pHandle, axis, ref homestate);

                Error_pHandle("ZAux_Direct_GetHomeStatus", error);

            } while (homestate == 0);

            return OPerationResult.Ok();
        }

        /// <summary>
        /// 轴运行状态 
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <returns></returns>
        public bool IsMoving(short axis)
        {
            OPerationResult result = CommonInitedValidate();
            if(!result.IsSucess) return false;
            int runState = -1; //运行状态.1-运行中，-1-未运行
            int error = 0;    //错误编号
            try
            {
                error=zmcaux.ZAux_Direct_GetIfIdle(_pHandle,axis,ref runState);
                Error_pHandle("ZAux_Direct_GetIfIdle", error);
                return runState == 0;           
            }
            catch (Exception)
            {

                return true;
            }
        }

        /// <summary>
        /// 读取输入信号状态
        /// </summary>
        /// <param name="piValue"></param>
        /// <returns></returns>
        public OPerationResult ReadAllGetIn(int[] inputSignals, ref uint[] inputSignalsFinal)
        {
            // 判断是否满足初始化条件
            var result = CommonInitedValidate();

            if (!result.IsSucess) return result;

            int error = 0;

            // 批量读取输入信号状态
            for (int i = 0; i < inputSignals.Length; i++)
            {
                UInt32 inputValueFinal = 0;
                error = zmcaux.ZAux_Direct_GetIn(_pHandle, inputSignals[i], ref inputValueFinal);
                inputSignalsFinal[i] = inputValueFinal;
            }

            if (error != 0)
            {
                return new OPerationResult()
                {
                    IsSucess = false,
                    ErrorMessage = "读取输入IO状态失败"
                };
            }

            return OPerationResult.Ok();
        }

        /// <summary>
        /// 读取单个输出
        /// </summary>
        /// <param name="outNum"></param>
        /// <returns></returns>
        public bool GetOutput(int outNum)
        {
            var result = CommonInitedValidate();
            if (!result.IsSucess) return false;
            uint data = 0;
            int error = 0;
            try
            {
                error = zmcaux.ZAux_Direct_GetOp(_pHandle, outNum, ref data);

                Error_pHandle("ZAux_Direct_GetOp", error);

                return data == 1;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// 写入单个输出值
        /// </summary>
        /// <param name="outNum"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public OPerationResult SetOutput(int outNum, bool value)
        {
            var result = CommonInitedValidate();
            if (!result.IsSucess) return result;

            int error = 0;
            try
            {
                error = zmcaux.ZAux_Direct_SetOp(_pHandle, outNum, value ? (uint)1 : 0);

                Error_pHandle("ZAux_Direct_SetOp", error);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();
        }

        /// <summary>
        /// 获取实时速度
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public float GetVel(short axis)
        {
            //判断是否满足初始化条件
            var result = CommonInitedValidate();

            if (!result.IsSucess) return 0.0f;

            //定义速度
            float vel = 0.0f;

            //定义错误码
            int error = 0;

            try
            {
                error = zmcaux.ZAux_Direct_GetVpSpeed(_pHandle, axis, ref vel);

                Error_pHandle("ZAux_Direct_GetVpSpeed", error);

                return vel;

            }
            catch (Exception)
            {
                return 0.0f;
            }
        }

        /// <summary>
        /// 获取实时位置
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public float GetPos(short axis)
        {

            //判断是否满足初始化条件
            var result = CommonInitedValidate();

            if (!result.IsSucess) return 0.0f;

            //定义位置
            float pos = 0.0f;

            //定义错误码
            int error = 0;

            try
            {

                error = zmcaux.ZAux_Direct_GetMpos(_pHandle, axis, ref pos);

                Error_pHandle("ZAux_Direct_GetMpos", error);

                return pos;

            }
            catch (Exception)
            {
                return 0.0f;
            }
        }

/*--------------------------------------总线轴控制------------------------------------*/
        /// <summary>
        /// 总线轴使能控制
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="isEnable"></param>
        /// <returns></returns>
        public OPerationResult SetEnable(short axis, bool isEnable)
        {
            var result = CommonInitedValidate();
            if (!result.IsSucess) return result;

            int error = 0; //错误编号
            try
            {
                error = zmcaux.ZAux_Direct_SetAxisEnable(_pHandle, axis, isEnable ? 0 : 1);
                Error_pHandle("ZAux_Direct_SetAxisEnable", error);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();
        }

        /// <summary>
        /// 总线轴使能获取
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public bool GetEnable(short axis)
        {
            var result = CommonInitedValidate();
            if (!result.IsSucess) return false;
            int enable = -1;//返回结果
            int error = 0; //错误代码
            try
            {
                error = zmcaux.ZAux_Direct_GetAxisEnable(_pHandle, axis, ref enable);
                Error_pHandle("ZAux_Direct_GetAxisEnable", error);
                return enable == 0;
            }
            catch (Exception ex)
            {
                return false;
            }

        }

        /// <summary>
        /// 总线轴错误清除
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public OPerationResult ClearError(short axis)
        {
            var result = CommonInitedValidate();
            if (!result.IsSucess) return result;

            int error = 0;
            try
            {
                error = zmcaux.ZAux_BusCmd_DriveClear(_pHandle, (uint)axis, 0);
                Error_pHandle("ZAux_BusCmd_DriveClear", error);
            }
            catch (Exception ex)
            {
                result.IsSucess = false;
                result.ErrorMessage = ex.Message;
                return result;
            }
            return OPerationResult.Ok();
        }


        /// <summary>
        /// 错误处理函数
        /// </summary>
        /// <param name="Commad">执行的命令</param>
        /// <param name="error">错误编号</param>
        private void Error_pHandle(string Commad,int error)
        {
            string result=string.Empty;
            switch (error)
            {
                case 0:
                    break;
                default:
                    result = string.Format("{0}"+"指令执行错误，错误编号为{1}",Commad,error);
                    break;
            }
            if (result.Length > 0)
            {
                throw new Exception(result);
            }
        }

        /// <summary>
        /// 通用初始化控制卡连接验证
        /// </summary>
        /// <returns>OPerationResult</returns>
        private OPerationResult CommonInitedValidate()
        {
            OPerationResult result = new OPerationResult();
            //判断轴是否连接
            if (!InitedOK)
            {
                result.IsSucess = false;
                result.ErrorMessage = "控制卡未连接";
                return result;
            }
            return OPerationResult.Ok();
        }

        /// <summary>
        /// 通用运动状态判断
        /// </summary>
        /// <param name="axis">轴号</param>
        /// <returns>OPerationResult</returns>
        private OPerationResult CommonInitedValidate(short axis)
        {
            OPerationResult result = CommonInitedValidate();
            if (!result.IsSucess) return result;
            //判断轴是否在运行中
            if (IsMoving(axis))
            {
                result.IsSucess = false;
                result.ErrorMessage= "轴正在运行中";
                return result;
            }
            return OPerationResult.Ok();
        }
    }
}
